<template>
  <div class="plane">
    <div style="display: flex;align-items: center;margin: 6px;">
      <img :src="planeSvg" alt="" style="width: 30px; height: auto;" />
      <div style="flex: 1;width: 0;">
        <div
          style="font-weight: bold;margin-left: 6px;font-size: 1rem;;text-align: left;text-overflow: ellipsis;white-space: nowrap;overflow: hidden;">
          今日工作
          <div style="font-size: 12px;color: var(--font-second-color);cursor: pointer;" @click.stop="showSelectDateFun">
            {{ formatDate(currentDate) }}
          </div>
        </div>
      </div>
      <div class="icon" style="width: 20px;margin-right: 2px;" @click.stop="movePrev()">
        <i class="fa-solid fa-chevron-left"></i>
      </div>
      <div class="icon" style="width: 20px;margin-right: 2px;" @click.stop="moveNowDate()">
        <i class="fa-solid fa-o"></i>
      </div>
      <div class="icon" style="width: 20px;margin-right: 2px;" @click.stop="moveNext()">
        <i class="fa-solid fa-chevron-right"></i>
      </div>
      <div class="icon" style="width: 20px;margin-right: 2px;" @click.stop="showPlane()">
        <i class="fa-solid fa-plus"></i>
      </div>
      <div class="icon" style="width: 20px;" @click.stop="openMenu">
        <i class="fa-solid fa-ellipsis-vertical" @click.stop="openMenu"></i>
      </div>
    </div>
    <a-date-picker ref="weekDatePickerRef" :value="currentDate" view="weekly" :hide-header="true"
      :hide-title="hideWeekDay" @change="changePickerDate" :attributes="attrs">

    </a-date-picker>
    <div ref="planeListContainer" class="plane-list"
      style="flex: 1;margin-top: 6px;padding-left: -8px;padding-right: -8px;overflow: auto;height: 0;">
      <div v-if="planeList.length === 0"
        style="height: 100%;display: flex;align-items: center;justify-content: center;">
        <a-loading v-if="onPlaneLoading"></a-loading>
        <div v-else-if="settingDialog.account && token"> 暂无计划 <a style="color: var(--primary-color)" href="#"
            @click.stop="showPlane()">点击添加</a></div>
        <div v-else> 还没配置账号 <a style="color: var(--primary-color)" href="#"
            @click.stop="settingDialog.visible = true;">绑定账号</a></div>
      </div>
      <div class="plane-item" :class="planeMenu.data.id === item.id ? 'plane-item-hover' : ''"
        v-for="(item, index) in planeList" :key="index" @click.stop="showPlane(item)"
        @contextmenu.prevent.stop="handlePlaneRightClick($event, item)">
        <div class="plane-status" :class="`plane-status-${item.status}`" :title="item.statusText"></div>
        <div class="plane-content">{{ item.name }}</div>
        <span class="tag" :class="item.duration > 0 ? 'blue' : 'gray'">{{ item.duration }}H</span>
      </div>
    </div>

    <teleport to="body">
      <transition name="a-dialog-fade">
        <div class="context-menu" style="padding: 4px 10px" v-if="showSelectDateDialog.visible"
          :style="{ left: showSelectDateDialog.x + 'px', top: showSelectDateDialog.y + 'px' }" @click.stop="">
          <a-date-picker :value="currentDate" @change="onSelectDate" :attributes="monthAttrs" @move="loadMonthPlane">

          </a-date-picker>
        </div>
      </transition>

      <transition name="a-dialog-fade">
        <div v-if="contextMenu.visible" class="context-menu"
          :style="{ left: contextMenu.x + 'px', top: contextMenu.y + 'px' }" @click.stop>
          <ul class="menu-list">
            <li class="item" @click.stop="loadDailyReport">周报</li>
            <li class="item" @click.stop="contextMenu.visible = false; settingDialog.visible = true">设置</li>
          </ul>
        </div>
      </transition>
      <transition name="a-dialog-fade">
        <div v-if="planeMenu.visible" class="context-menu"
          :style="{ left: planeMenu.x + 'px', top: planeMenu.y + 'px' }" @click.stop>
          <ul class="menu-list">
            <li class="item" @click.stop="updateStatus(4)" v-if="planeMenu.data.status !== 4">挂起</li>
            <li class="item" @click.stop="updateStatus(2)" v-if="planeMenu.data.status !== 2">进行中</li>
            <li class="item" @click.stop="updateStatus(3)" v-if="planeMenu.data.status !== 3">仅完成</li>
            <li class="item" @click.stop="updateStatus(3, true)" v-if="planeMenu.data.status !== 3">完成且进度100%</li>
            <li class="item" @click.stop="creatNext()">延至下一日</li>
            <li class="item error" @click.stop="deletePlane()">删除</li>
          </ul>
        </div>
      </transition>
    </teleport>

    <a-dialog v-model="settingDialog.visible" :shake="!onLoading && !!settingDialog.errorMessage">
      <div class="dialog-title">周报账号设置</div>
      <div style="margin-bottom:8px;">
        <label>账号：</label>
        <input class="input" v-model="settingDialog.account" maxlength="20" placeholder="请输入周报系统账号" />
      </div>
      <div style="margin-bottom:8px;">
        <label>密码：</label>
        <input class="input" v-model="settingDialog.passd" maxlength="30" placeholder="请输入周报系统密码" type="password" />
      </div>
      <div v-if="!onLoading && settingDialog.errorMessage"
        style="color: var(--error-color);margin: 10px;text-align: center;">{{
          settingDialog.errorMessage
        }}
      </div>
      <div style="text-align:right;margin-top: 20px;">
        <button class="button" @click.stop="settingDialog.visible = false">取消</button>
        <button class="button btn-primary" @click.stop="login">确定</button>
      </div>
    </a-dialog>

    <a-dialog v-model="dailyReportDialog.visible">
      <div style="display: flex;flex-direction: column;max-height: 100%;">
        <div class="dialog-title">导出周报</div>
        <div style="display: flex;flex: 1;height: 0;">
          <div style="margin-right: 20px;">
            <div style="text-align: center;color: var(--font-second-color);">
              导出范围
              <span style="color: var(--font-color);font-weight: bold;">
                {{ formatDate(dailyReportDate.start) }}
              </span>
              至
              <span style="color: var(--font-color);font-weight: bold;">
                {{ formatDate(dailyReportDate.end) }}
              </span>
            </div>
            <v-date-picker mode='range' v-model="dailyReportDate" is-range :rows="2">
            </v-date-picker>
          </div>
          <div style="max-height: 100%;overflow: auto;min-width: 400px;">
            <p v-html="dailyReportDialog.content" style="white-space: pre-line">
            </p>
          </div>
        </div>
        <div style="text-align:right;margin-top: 20px;">
          <button class="button" @click.stop="dailyReportDialog.visible = false">取消</button>
          <button class="button btn-primary" @click.stop="copyText(dailyReportDialog.content)">拷贝</button>
          <button class="button btn-primary" @click.stop="sendEmail">发送邮件</button>
        </div>
      </div>
    </a-dialog>

    <a-dialog v-model="planeDialog.visible" @close="showSelectDate = false" :shake="!!formErr">
      <div class="form" @click="showSelectDate = false">
        <div v-if="selectProject" style="max-height: 100%;display: flex;flex-direction: column;"
          :style="{ width: projectsHistory.length > 0 ? '700px' : '400px' }">
          <div style="margin-bottom: 20px;display: flex;align-items: center;">
            <button class="icon" style="cursor: pointer;padding: 4px 6px;" @click="selectProject = false">
              <i class="fa-solid fa-arrow-left-long"></i>
            </button>
            <div style="font-size: 18px;margin-left: 20px;font-weight: bold;">选择项目</div>
          </div>
          <div style="display: flex;flex: 1;height: 0;">
            <div style="display: flex;flex-direction: column;flex: 1;" v-if="projectsHistory.length > 0">
              <div
                style="margin: 0 14px;margin-bottom: 10px;line-height: 30px;max-height: 30px;display: flex;align-items: center;">
                <div style="flex: 1;">最近使用</div>
                <a href="#" style="color: var(--primary-color);" @click="clearProjectHistory">清空历史</a>
              </div>
              <div class="projects">
                <div class="project-item-parent" v-for="(item, index) in projectsHistory" :key="index"
                  @click="selectedProject(item)">
                  <div class="project-item">
                    <div class="title">{{ item.name }}
                      <span class="tag green dark">{{ item.appVersion }}</span>
                    </div>
                    <div class="product">产品：{{ item.productName }}</div>
                    <div class="bottom">
                      <div class="time">计划：{{
                        item.startTime }} - {{ item.endTime }}</div>
                      <div style="flex: 1;">
                      </div>
                      <div class="user">负责人：{{ item.chargeUser }}</div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
            <div style="width: 2px;margin: 0 10px;background-color: rgba(255, 255, 255, 0.1);border-radius: 10px;"
              v-if="projectsHistory.length > 0">
            </div>
            <div style="display: flex;flex-direction: column;flex: 1;">
              <div style="max-height: 30px;margin-bottom: 10px;display: flex;align-items: center;">
                <div>查找：</div>
                <input class="input" v-model="queryProjectsForm.searchKey" placeholder="请输入项目名称"
                  @keyup.enter="loadProjects(true)" />
              </div>
              <div class="projects" style="flex: 1;height: 100%;position: relative;">
                <div v-if="!queryProjectsForm.searchKey && myProjects.length > 0">
                  <div class="list-title">我参与并且正在进行的项目</div>
                  <div class="project-item-parent blue-bg" v-for="(item, index) in myProjects" :key="index"
                    @click="selectedProject(item)">
                    <div class="project-item">
                      <div class="title">{{ item.name }}
                        <span class="tag green dark">{{ item.appVersion }}</span>
                      </div>
                      <div class="product">产品：{{ item.productName }}</div>
                      <div class="status">状态：{{ item.statusName }}</div>
                      <a-process :value="item.position" :text="`${item.position}%`"
                        :color="item.error ? `var(--error-color)` : item.position == 100 ? `var(--success-color)` : `var(--primary-color)`"></a-process>
                      <div class="bottom">
                        <div class="time" :class="{ 'error': item.error }">计划：{{
                          item.startTime }} - {{ item.endTime }}</div>
                        <div style="flex: 1;">
                        </div>
                        <div class="user">负责人：{{ item.chargeUser }}</div>
                      </div>
                    </div>
                  </div>
                  <div class="list-title">其他正在进行的项目</div>
                </div>
                <div class="project-item-parent" v-for="(item, index) in projects" :key="index"
                  @click="selectedProject(item)">
                  <div class="project-item">
                    <div class="title">{{ item.name }}
                      <span class="tag green dark">{{ item.appVersion }}</span>
                    </div>
                    <div class="product">产品：{{ item.productName }}</div>
                    <div class="status">状态：{{ item.statusName }}</div>
                    <a-process :value="item.position" :text="`${item.position}%`"
                      :color="item.error ? `var(--error-color)` : item.position == 100 ? `var(--success-color)` : `var(--primary-color)`"></a-process>
                    <div class="bottom">
                      <div class="time" :class="{ error: item.error }">计划：{{
                        item.startTime }} - {{ item.endTime }}</div>
                      <div style="flex: 1;">
                      </div>
                      <div class="user">负责人：{{ item.chargeUser }}</div>
                    </div>
                  </div>
                </div>
                <div
                  style="position: absolute;top: 0;left: 0;bottom: 0;right: 0;display: flex;align-items: center;justify-content: center;"
                  v-if="projects.length == 0">
                  <a-loading v-if="queryProjectsForm.onLoading"></a-loading>
                  <div v-else style="color: var(--font-second-color);">
                    暂无项目
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>

        <div v-else-if="selectProjectTask" style="max-height: 100%;display: flex;flex-direction: column;"
          :style="{ width: workTaskListHistory.length > 0 ? '700px' : '400px' }">
          <div style="margin-bottom: 20px;display: flex;align-items: center;">
            <i class="fa-solid fa-arrow-left-long" style="cursor: pointer;" @click="selectProjectTask = false"></i>
            <div style="font-size: 18px;margin-left: 20px;font-weight: bold;">选择任务</div>
          </div>
          <div style="display: flex;flex: 1;height: 0;">
            <div style="display: flex;flex-direction: column;flex: 1;" v-if="workTaskListHistory.length > 0">
              <div
                style="margin: 0 14px;margin-bottom: 10px;line-height: 30px;max-height: 30px;display: flex;align-items: center;">
                <div style="flex: 1;">最近使用</div>
                <a href="#" style="color: var(--primary-color);" @click="clearWorkTaskHistory">清空历史</a>
              </div>
              <div class="projects">
                <div class="project-item-parent" v-for="(item, index) in workTaskListHistory" :key="index"
                  @click="selectedProjectTask(item)">
                  <div class="project-item">
                    <div class="title">
                      {{ item.parentTaskName ? item.parentTaskName + ' / ' : '' }} {{ item.name }}
                    </div>
                    <div class="bottom">
                      <div class="time">计划：{{
                        item.startDate }} - {{ item.endDate }}</div>
                      <div style="flex: 1;">
                      </div>
                      <div class="user">负责人：{{ item.userName }}</div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
            <div style="width: 2px;margin: 0 10px;background-color: rgba(255, 255, 255, 0.1);border-radius: 10px;"
              v-if="workTaskListHistory.length > 0">
            </div>
            <div style="display: flex;flex-direction: column;flex: 1;">
              <div style="max-height: 30px;margin-bottom: 10px;display: flex;align-items: center;">
                <div>查找：</div>
                <input class="input" v-model="queryProjectsTaskForm.searchKey" placeholder="请输入任务名称"
                  @keyup.enter="loadWorkTask()" />
              </div>
              <div class="projects" style="flex: 1;height: 100%;position: relative;">
                <div v-if="!queryProjectsTaskForm.searchKey && myWorkTaskList.length > 0">
                  <div class="list-title">我参与并且正在进行的任务</div>
                  <div class="project-item-parent blue-bg" v-for="(item, index) in myWorkTaskList" :key="index"
                    @click="selectedProjectTask(item)">
                    <div class="project-item">
                      <div class="title">
                        {{ item.parentTaskName ? item.parentTaskName + ' / ' : '' }} {{ item.name }}
                        <span class="tag green dark" :class="{ gray: item.taskType == 2 }">
                          {{ item.taskTypeText }}
                        </span>
                      </div>
                      <a-process :value="item.position" :text="`${item.position}%`"
                        :color="item.error ? `var(--error-color)` : item.position == 100 ? `var(--success-color)` : `var(--primary-color)`"></a-process>
                      <div class="bottom">
                        <div class="time" :class="{ error: item.error }">计划：{{
                          item.startDate }} - {{ item.endDate }}</div>
                        <div style="flex: 1;">
                        </div>
                        <div class="user">负责人：{{ item.userName }}</div>
                      </div>
                    </div>
                  </div>
                  <div class="list-title">其他正在进行的任务</div>
                </div>

                <div class="project-item-parent" v-for="(item, index) in workTaskList" :key="index"
                  v-show="!myWorkTaskIds.includes(item.id)" @click="selectedProjectTask(item)">
                  <div class="project-item">
                    <div class="title">
                      {{ item.parentTaskName ? item.parentTaskName + ' / ' : '' }} {{ item.name }}
                      <span class="tag green dark" :class="{ gray: item.taskType == 2 }">
                        {{ item.taskTypeText }}
                      </span>
                    </div>
                    <a-process :value="item.position" :text="`${item.position}%`"
                      :color="item.error ? `var(--error-color)` : item.position == 100 ? `var(--success-color)` : `var(--primary-color)`"></a-process>
                    <div class="bottom">
                      <div class="time" :class="{ error: item.error }">计划：{{
                        item.startDate }} - {{ item.endDate }}</div>
                      <div style="flex: 1;">
                      </div>
                      <div class="user">负责人：{{ item.userName }}</div>
                    </div>
                  </div>
                </div>
                <div
                  style="position: absolute;top: 0;left: 0;bottom: 0;right: 0;display: flex;align-items: center;justify-content: center;"
                  v-if="workTaskList.length == 0">
                  <a-loading v-if="queryProjectsTaskForm.onLoading"></a-loading>
                  <div v-else style="color: var(--font-second-color);">
                    暂无任务
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>

        <div v-else-if="selectRds" style="max-height: 100%;display: flex;flex-direction: column;"
          :style="{ width: rdsHistory.length > 0 ? '700px' : '400px' }">
          <div style="margin-bottom: 20px;display: flex;align-items: center;">
            <i class="fa-solid fa-arrow-left-long" style="cursor: pointer;" @click="selectRds = false"></i>
            <div style="font-size: 18px;margin-left: 20px;font-weight: bold;">选择RD</div>
          </div>
          <div style="display: flex;flex: 1;height: 0;">
            <div style="display: flex;flex-direction: column;flex: 1;" v-if="rdsHistory.length > 0">
              <div
                style="margin: 0 14px;margin-bottom: 10px;line-height: 30px;max-height: 30px;display: flex;align-items: center;">
                <div style="flex: 1;">最近使用</div>
                <a href="#" style="color: var(--primary-color);" @click="clearRdHistory">清空历史</a>
              </div>
              <div class="projects">
                <div class="project-item-parent" v-for="(item, index) in rdsHistory" :key="index"
                  @click="selectedRd(item)">
                  <div class="project-item">
                    <div class="title">{{ item.title }}
                      <span class="tag green dark">{{ item.name }}</span>
                    </div>
                    <p class="product">{{ item.remark }}</p>
                  </div>
                </div>
              </div>
            </div>
            <div style="width: 2px;margin: 0 10px;background-color: rgba(255, 255, 255, 0.1);border-radius: 10px;"
              v-if="rdsHistory.length > 0">
            </div>
            <div style="display: flex;flex-direction: column;flex: 1;">
              <div style="max-height: 30px;margin-bottom: 10px;display: flex;align-items: center;">
                <div>查找：</div>
                <input class="input" v-model="queryRdForm.searchKey" placeholder="请输入RD名称" />
              </div>
              <div class="projects" style="flex: 1;height: 100%;position: relative;">
                <div class="project-item-parent" v-for="(item, index) in rds" :key="index"
                  v-show="!queryRdForm.searchKey || item.title.includes(queryRdForm.searchKey)"
                  @click="selectedRd(item)">
                  <div class="project-item">
                    <div class="title">
                      <span class="tag blue dark">{{ item.name }}</span>
                      {{ item.title }}
                    </div>
                    <p class="product">{{ item.remark }}</p>
                  </div>
                </div>
                <div
                  style="position: absolute;top: 0;left: 0;bottom: 0;right: 0;display: flex;align-items: center;justify-content: center;"
                  v-if="rds.length == 0">
                  <div style="color: var(--font-second-color);">
                    暂无任务
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>

        <div v-else style="display: inline-flex;flex-direction: column">
          <div style="margin-bottom: 20px;text-align: center;font-size: 18px;font-weight: bold;">编辑待办任务</div>
          <div style="flex: 1;overflow: auto;">
            <div class="form-item">
              <label :class="planeDialog.data.currentDate ? '' : 'err'">
                <span class="require"></span>
                任务日期：
              </label>
              <input class="input" :disabled="planeDialog.data.id" v-model="planeDialog.data.currentDate" maxlength="20"
                placeholder="请选择日期" @click.stop="showSelectDate = true" readonly />
            </div>
            <transition name="a-dialog-fade">
              <div class="date-picker" v-if="showSelectDate" @click.stop="">
                <v-date-picker v-model="planeDialog.data.currentDate" @dayclick="changePlaneDate">
                </v-date-picker>
              </div>
            </transition>
            <div class="form-item">
              <label :class="planeDialog.data.type ? '' : 'err'">
                <span class="require"></span>
                任务类型：
              </label>
              <select v-model="planeDialog.data.type" class="input" :disabled="planeDialog.data.id"
                @change="planeDialog.data.projectId = ''; planeDialog.data.projectName = '';">
                <option v-for="type in typeEnums" :key="type.key" :value="type.key">
                  {{ type.text }}
                </option>
              </select>
            </div>
            <div class="form-item" v-if="planeDialog.data.type != 4">
              <label :class="planeDialog.data.projectName ? '' : 'err'">
                <span class="require"></span>
                所属项目：
              </label>
              <input class="input" :disabled="planeDialog.data.id" v-model="planeDialog.data.projectName"
                placeholder="请选择所属项目" readonly @click="selectProject = true; loadProjects(true)" />
            </div>

            <div class="form-item">
              <label :class="planeDialog.data.rdId ? '' : 'err'">
                <span class="require"></span>
                所属RD：
              </label>
              <input class="input" :disabled="planeDialog.data.id"
                :value="planeDialog.data.rdId ? `${planeDialog.data.rdName}${planeDialog.data.rdTitle ? '(' + planeDialog.data.rdTitle + ')' : ''}` : ''"
                placeholder="请选择所属RD" readonly @click="selectRds = true;" />
            </div>
            <div class="form-item"
              v-if="(planeDialog.data.projectId || planeDialog.data.workTaskId) && planeDialog.data.type != 4">
              <label :class="planeDialog.data.workTaskName ? '' : 'err'">
                <span class="require"></span>
                工作任务：
              </label>
              <input class="input" :disabled="planeDialog.data.id" v-model="planeDialog.data.workTaskName"
                placeholder="请选择工作任务" readonly @click="selectProjectTask = true; loadWorkTask()" />
            </div>

            <div class="form-item">
              <label :class="planeDialog.data.type == 4 && !planeDialog.data.zentaoUrl ? 'err' : ''">
                <span class="require"></span>
                关联bug：
              </label>
              <input class="input" v-model="planeDialog.data.zentaoUrl" placeholder="请填写禅道地址" />
            </div>

            <div class="form-item">
              <label :class="planeDialog.data.name ? '' : 'err'">
                <span class="require"></span>
                内容：
              </label>
              <input class="input" :disabled="planeDialog.data.id" v-model="planeDialog.data.name" maxlength="200"
                placeholder="请输入具体工作内容" />
            </div>
            <div class="form-item">
              <div>
                <label :class="maxTime > 0 ? '' : 'err'">
                  <span class="require"></span>
                  时长{{ maxTime === 0 ? '不足' : '' }}：
                </label>

                <div v-if="workTime > 0"
                  style="font-size: 12px;color: var(--font-second-color);text-align: right;margin-right: 10px;">
                  {{ '已工作' + workTime + 'H' }}
                </div>
              </div>


              <a-slider :disabled="maxTime == 0" style="flex: 1;" :value="planeDialog.data.duration"
                :text="`${planeDialog.data.duration}H`" @change="(e) => {
                  planeDialog.data.duration = e;
                }" :min="0" :max="maxTime == 0 ? 0.1 : maxTime" :step="0.5" text-width="40px" />
            </div>
            <div class="form-item">
              <label>
                <span class="require"></span>
                进度：
              </label>
              <a-slider style="flex: 1;" v-model="planeDialog.data.position" @change="changePosition"
                :text="`${planeDialog.data.position}%`" :min="0" :max="100" :step="1" text-width="40px" />
            </div>
            <div class="form-item">
              <label>
                <span class="require"></span>
                状态：
              </label>
              <div style="flex: 1;display: flex;align-items: center;">
                <div class="plane-status" style="margin-right: 10px;"
                  :class="`plane-status-${planeDialog.data.status}`">
                </div>
                <select v-model="planeDialog.data.status" class="input">
                  <option v-for="type in statusEnums" :key="type.key" :value="type.key">
                    {{ type.text }}
                  </option>
                </select>
              </div>
            </div>
            <div class="form-item">
              <label>备注：</label>
              <textarea class="input" v-model="planeDialog.data.remark" maxlength="20" placeholder="请输入备注内容"
                style="max-height: 200px;max-width: 300px;" />
            </div>
          </div>

          <div v-if="formErr" style="color: var(--error-color);margin: 10px;text-align: center;">
            {{ formErr }}
          </div>
          <div style="text-align:right;margin-top: 20px;">
            <button class="button" @click.stop="planeDialog.visible = false">取消</button>
            <button style="display: inline-flex;align-items: center;" class="button btn-primary"
              @click.stop="submitPlane" :disabled="onsubmit">
              <span v-if="onsubmit" class="spinner"
                style="display:inline-block;width:12px;height:12px;border:2px solid #fff;border-top:2px solid #409eff;border-radius:50%;vertical-align:middle;margin-right:6px;"></span>
              <span v-if="!onsubmit">确定</span>
              <span v-else>提交中</span>
            </button>
          </div>
        </div>
      </div>
    </a-dialog>

    <!-- 删除 -->
    <a-dialog v-model="delPlaneDialog.visible">
      <div class="dialog-title">删除日志</div>
      <div>
        确认删除 '{{ delPlaneDialog.data.name }}'？
      </div>
      <div style="text-align:right;margin-top: 20px;">
        <button class="button" @click.stop="delPlaneDialog.visible = false">取消</button>
        <button class="button btn-error" @click.stop="deletePlaneConfirm" :disabled="onsubmit">确定</button>
      </div>
    </a-dialog>
  </div>
</template>
<script>
export default {
  name: "a-plane",
}
</script>
<script setup>
import { ref, onMounted, onUnmounted, watch } from 'vue';
import axios from 'axios';
// 节假日判断相关
const isWorkday = ref(true); // 默认工作日
const holidayInfo = ref(null);

async function checkChinaHoliday(date) {
  // date: Date对象
  const y = date.getFullYear();
  const m = String(date.getMonth() + 1).padStart(2, '0');
  const d = String(date.getDate()).padStart(2, '0');
  const dateStr = `${y}-${m}-${d}`;
  try {
    const res = await axios.get(`https://timor.tech/api/holiday/info/${dateStr}`);
    if (res.data && res.data.type) {
      holidayInfo.value = res.data;
      // type.type: 0工作日, 1周末, 2节日, 3调休
      isWorkday.value = res.data.type.type === 0 || res.data.type.type === 3;
    } else {
      // fallback: 仅按周判断
      const day = date.getDay();
      isWorkday.value = day >= 1 && day <= 5;
    }
  } catch (e) {
    // 网络异常时fallback
    const day = date.getDay();
    isWorkday.value = day >= 1 && day <= 5;
  }
}
import ADialog from "@/components/a-dialog.vue";
import ALoading from "@/components/a-loading.vue";
import ADatePicker from "@/components/a-date-picker.vue";
import planeSvg from '/public/assets/app-logo/plane.svg';
import { storage } from "@/lib/storage";
import ipdApi from '@/api/ipd_api.js';
import JSEncrypt from 'jsencrypt';
import aSlider from '@/components/a-slider.vue';
import aProcess from '@/components/a-process.vue';
import { useToast } from 'vue-toastification'

const toast = useToast()


// 记录当天第一次启动时间
const workTime = ref(0);
const monthAttrs = ref([]);
const attrs = ref([]);
const onPlaneLoading = ref(false);
const planeList = ref([]);
const contextMenu = ref({
  visible: false,
  x: 0,
  y: 0,
});
const planeMenu = ref({
  visible: false,
  x: 0,
  y: 0,
  data: {}
});

const handlePlaneRightClick = (e, item) => {
  planeMenu.value = {
    visible: true,
    x: e.clientX,
    y: e.clientY,
    data: item
  };
};
const selectProject = ref(false);
const selectRds = ref(false);
const selectProjectTask = ref(false);
const showSelectDate = ref(false);
const showSelectDateDialog = ref({
  visible: false,
  x: 0,
  y: 0,
});
const hideWeekDay = ref(false);
const weekDatePickerRef = ref(null);
const onLoading = ref(false);
const formErr = ref('');
const token = ref("");
const currentDate = ref(new Date());

const maxTime = ref(0);
const typeEnums = ref([]);
const statusEnums = ref([]);
const projects = ref([]);
const rds = ref([]); // rd列表
const rdsHistory = ref([]); // rd列表
const myProjects = ref([]); // 我参与并且正在进行的项目
const myProjectsIds = ref([]); // 我参与并且正在进行的项目ID
const projectsHistory = ref([]);
const workTaskList = ref([]);
const myWorkTaskList = ref([]);
const myWorkTaskIds = ref([]);
const workTaskListHistory = ref([]);
const queryProjectsTaskForm = ref({
  pageIndex: 1,
  pageSize: 100,
  projectId: '',
  searchKey: null,
  onLoading: false,
});
const queryRdForm = ref({
  pageIndex: 1,
  pageSize: 1000,
  searchKey: null,
});


const dailyReportDate = ref({
  start: new Date(),
  end: new Date()
})
const dailyReportDialog = ref({
  visible: false,
  content: '',
});

const delPlaneDialog = ref({
  visible: false,
  data: {},
});

const settingDialog = ref({
  visible: false,
  account: '',
  passd: '',
  errorMessage: ''
});

const queryProjectsForm = ref({
  pageIndex: 1,
  pageSize: 100,
  statusDoing: true,
  type: 1,
  productEnable: true,
  onLoading: true,
  searchKey: null
})

const onsubmit = ref(false);
const planeDialog = ref({
  visible: false,
  data: {
    currentDate: '',
    createTime: '',
    endTime: '',
    externalSupportId: '',
    externalSupportName: '',
    externalSupportTaskType: '',
    externalSupportTaskTypeText: '',
    externalSupportType: '',
    externalSupportTypeText: '',
    externalSupportUser: '',
    externalSupportZentaoUrl: '',
    zentaoUrl: '',
    id: '',
    name: '',
    position: 0,
    duration: 0,
    projectId: '',
    projectName: '',
    rdId: '',
    rdName: '',
    remark: '',
    reviewRemark: '',
    reviewStatus: 1,
    reviewStatusText: '待审核',
    reviewTime: '',
    status: 1,
    statusText: '计划',
    type: 1,
    typeText: 'IPD',
    updateTime: '',
    userId: '',
    userName: '',
    workTaskId: '',
    workTaskName: '',
  },
  errorMessage: ''
});


const movePrev = () => {
  currentDate.value = weekDatePickerRef.value.movePrev();
  console.log('currentDate.value', currentDate.value);
  getCurrentWeek(currentDate.value);
  currentDate.value = dailyReportDate.value.start
  loadPlane();
}
const moveNext = () => {
  currentDate.value = weekDatePickerRef.value.moveNext();
  console.log('currentDate.value', currentDate.value);
  getCurrentWeek(currentDate.value);
  currentDate.value = dailyReportDate.value.start
  loadPlane();
}
const moveNowDate = () => {
  currentDate.value = new Date();
  weekDatePickerRef.value.moveToDate(currentDate.value);
  getCurrentWeek(currentDate.value);
  loadPlane();
}

const openMenu = (e) => {
  contextMenu.value.x = e.clientX;
  contextMenu.value.y = e.clientY;
  contextMenu.value.visible = true;
  planeMenu.value.visible = false;
};

const showSelectDateFun = (e) => {
  showSelectDateDialog.value.x = e.clientX;
  showSelectDateDialog.value.y = e.clientY;
  showSelectDateDialog.value.visible = true;
  loadMonthPlane(currentDate.value);
};

const closeMenu = () => {
  showSelectDate.value = false
  planeMenu.value.visible = false;
  contextMenu.value.visible = false;
  showSelectDateDialog.value.visible = false;
  planeMenu.value.data = {};
};

const showPlane = (item) => {
  storage.get(`plane-data`).then((val) => {
    let old = val ? JSON.parse(val) : {
      projectId: '',
      projectName: '',
      workTaskId: '',
      workTaskName: '',
      type: 1,
    }
    formErr.value = ''
    if (item) {
      item.rdId = item.rdId ? item.rdId : old.rdId;
      item.rdName = item.rdName ? item.rdName : old.rdName;
      item.projectId = item.projectId ? item.projectId : old.projectId;
      item.projectName = item.projectName ? item.projectName : old.projectName;
      item.workTaskId = item.workTaskId ? item.workTaskId : old.workTaskId;
      item.workTaskName = item.workTaskName ? item.workTaskName : old.workTaskName;
      item.type = item.type ? item.type : old.type;
      item.zentaoUrl = item.zentaoUrl ? item.zentaoUrl : item.externalSupportZentaoUrl;
      planeDialog.value.data = JSON.parse(JSON.stringify(item));
      if (item.projectId) {
        ipdApi.projectItem(item.projectId, token.value, (r) => {
          planeDialog.value.data.projectName = r.data.name + ' ' + r.data.appVersion;
        })
      }
    } else {
      planeDialog.value.data = {
        duration: 0.0,
        position: 0,
        status: 1,
        currentDate: formatDate(currentDate.value),
        projectId: old.projectId,
        workTaskId: old.workTaskId,
        type: old.type,
        projectName: old.projectName,
        workTaskName: old.workTaskName,
        rdId: old.rdId,
        rdName: old.rdName,
      }
    }
    const now = new Date();
    if (!planeDialog.value.data.currentDate || planeDialog.value.data.currentDate == formatDate(new Date())) {
      const target = new Date(now);
      target.setHours(19, 0, 0, 0);
      const diffMs = now - target;
      const diffHours = diffMs / (1000 * 60 * 60);
      maxTime.value = 7.5 + (diffHours > 0 ? diffHours : 0);
    } else {
      maxTime.value = 12.5;
    }

    planeList.value.forEach((v) => {
      if (item && v.id === item.id) {
        return
      }
      maxTime.value = maxTime.value - v.duration;
    })
    maxTime.value = parseFloat(maxTime.value.toFixed(1));

    selectProject.value = false;
    selectProjectTask.value = false;
    planeDialog.value.visible = true;
    contextMenu.value.visible = false;
    planeMenu.value.visible = false;
    planeMenu.value.data = {};
  });
};

const planeListContainer = ref(null);

const handlePlaneListScroll = (event) => {
  const container = event.target;
  hideWeekDay.value = container.scrollTop > (hideWeekDay.value ? 0 : 50)
};

const clearProjectHistory = () => {
  projectsHistory.value = [];
  storage.remove(`plane-projects-history-${queryProjectsForm.value.type}`);
}

const selectedProject = (item) => {
  if (item.projectId === planeDialog.value.data.projectId) {
    return
  }
  planeDialog.value.data.rdId = item.rdId;
  planeDialog.value.data.rdName = item.rdName;
  planeDialog.value.data.type = item.type;
  planeDialog.value.data.projectId = item.id;
  planeDialog.value.data.projectName = item.name + ' ' + item.appVersion;
  planeDialog.value.data.workTaskId = '';
  planeDialog.value.data.workTaskName = '';
  planeDialog.value.data.duration = 0;
  planeDialog.value.data.position = 0;
  planeDialog.value.data.status = 1;
  selectProject.value = false;
  queryProjectsTaskForm.value.searchKey = null;
  for (const index in projectsHistory.value) {
    if (projectsHistory.value[index].id == item.id) {
      projectsHistory.value.splice(index, 1);
      projectsHistory.value.unshift(item);
      storage.set(`plane-projects-history-${queryProjectsForm.value.type}`, JSON.stringify(projectsHistory.value));
      return
    }
  }
  projectsHistory.value.unshift(item);
  if (projectsHistory.value.length > 5) {
    projectsHistory.value.pop();
  }
  storage.set(`plane-projects-history-${queryProjectsForm.value.type}`, JSON.stringify(projectsHistory.value));
};

const clearWorkTaskHistory = () => {
  workTaskListHistory.value = [];
  storage.remove(`plane-projects-task-history-${planeDialog.value.data.projectId}`);
}
const selectedProjectTask = (item) => {
  planeDialog.value.data.workTaskId = item.id;
  planeDialog.value.data.workTaskName = item.name;
  if (!planeDialog.value.data.name) {
    planeDialog.value.data.name = item.name;
  }
  selectProjectTask.value = false;
  queryProjectsTaskForm.value.searchKey = null;
  for (const index in workTaskListHistory.value) {
    if (workTaskListHistory.value[index].id == item.id) {
      workTaskListHistory.value.splice(index, 1);
      workTaskListHistory.value.unshift(item);
      storage.set(`plane-projects-task-history-${planeDialog.value.data.projectId}`, JSON.stringify(workTaskListHistory.value));
      return
    }
  }
  workTaskListHistory.value.unshift(item);
  if (workTaskListHistory.value.length > 5) {
    workTaskListHistory.value.pop();
  }
  storage.set(`plane-projects-task-history-${planeDialog.value.data.projectId}`, JSON.stringify(workTaskListHistory.value));
};
const clearRdHistory = () => {
  rdsHistory.value = [];
  storage.remove(`plane-rd-history`);
}
const selectedRd = (item) => {
  planeDialog.value.data.rdId = item.id;
  planeDialog.value.data.rdName = item.name;
  planeDialog.value.data.rdTitle = item.title;
  selectRds.value = false;
  queryRdForm.value.searchKey = null;
  for (const index in rdsHistory.value) {
    if (rdsHistory.value[index].id == item.id) {
      rdsHistory.value.splice(index, 1);
      rdsHistory.value.unshift(item);
      storage.set(`plane-rd-history`, JSON.stringify(rdsHistory.value));
      return
    }
  }
  rdsHistory.value.unshift(item);
  if (rdsHistory.value.length > 5) {
    rdsHistory.value.pop();
  }
  storage.set(`plane-rd-history`, JSON.stringify(rdsHistory.value));
};

/**
 * 加载我参与的项目
 * @param reload
 */
const loadMyProjects = (callback) => {
  ipdApi.myProjects({
    pageIndex: 1,
    pageSize: 100,
    statusDoing: true,
    productEnable: true,
    member: true
  }, token.value, (r) => {
    if (r.success) {
      const now = new Date().getTime();
      r.data.content.forEach(item => {
        item.sortStartTime = new Date(item.startTime).getTime();
        item.sortEndTime = new Date(item.endTime).getTime();
        if (item.position < 100 && item.sortEndTime < now) {
          item.error = true;
        }
      });
      myProjects.value = sortByTimeRange(r.data.content);
      myProjectsIds.value = []
      myProjects.value.forEach(item => {
        myProjectsIds.value.push(item.id);
      })
      if (callback) {
        callback();
      }
    } else {
      if (r.code === -10000) {
        login(loadMyProjects());
      }
    }
  });
};
const loadRds = () => {
  ipdApi.rds(queryRdForm.value, token.value, (r) => {
    if (r.success) {
      rds.value = r.data
    } else {
      if (r.code === -10000) {
        login(loadRds());
      }
    }
  });

  storage.get(`plane-rd-history`).then((r) => {
    if (r) {
      try {
        rdsHistory.value = JSON.parse(r);
      } catch (e) {
        console.error('解析RD历史失败:', e);
      }
    }
  })
};
const sortByTimeRange = (data) => {
  return data.sort((a, b) => {
    // 优先级2：已完成的任务(position=100)放到最后
    if (a.position === 100 && b.position !== 100) return 1;
    if (a.position !== 100 && b.position === 100) return -1;
    // 优先级3：相同条件下按开始时间升序
    return a.sortStartTime - b.sortStartTime;
  });
};
const loadProjects = (reload) => {
  queryProjectsForm.value.type = planeDialog.value.data.type;
  if (reload) {
    queryProjectsForm.value.pageIndex = 1;
    projects.value = [];
    storage.get(`plane-projects-history-${queryProjectsForm.value.type}`).then((r) => {
      if (r) {
        try {
          projectsHistory.value = JSON.parse(r);
        } catch (e) {
          console.error('解析项目历史失败:', e);
        }
      }
    })
  }
  queryProjectsForm.value.onLoading = true;
  ipdApi.projects(queryProjectsForm.value, token.value, (r) => {
    if (r.success) {
      const now = new Date().getTime();
      r.data.content.forEach(item => {
        if (!myProjectsIds.value.includes(item.id) || queryProjectsForm.value.searchKey) {
          if (item.endTime && item.position < 100 && new Date(item.endTime).getTime() < now) {
            item.error = true;
          }
          projects.value.push(item);
        }
      });
      queryProjectsForm.value.onLoading = false;
    } else {
      console.error('获取项目失败:', r);
      if (r.code === -10000) {
        login(loadProjects());
      }
    }
  });
};

const loadDailyReport = () => {
  dailyReportDialog.value.visible = true;
  contextMenu.value.visible = false;
  ipdApi.dailyReport(formatDate(dailyReportDate.value.start), formatDate(dailyReportDate.value.end), token.value, (r) => {
    if (r.success) {
      dailyReportDialog.value.content = r.data;
    } else {
      console.error('获取项目失败:', r);
      if (r.code === -10000) {
        login(loadDailyReport());
      }
    }
  });
};

const onSelectDate = (day, event) => {
  currentDate.value = day;
  getCurrentWeek(currentDate.value);
  loadPlane();
  showSelectDateDialog.value.visible = false;
}

const creatNext = () => {
  planeMenu.value.visible = false;
  let form = JSON.parse(JSON.stringify(planeMenu.value.data));
  planeMenu.value.data = {}
  form.id = null;
  let date = new Date(form.currentDate);
  date.setDate(date.getDate() + 1);
  form.status = 1;
  form.duration = 0;
  form.position = 0;
  form.currentDate = formatDate(date);
  ipdApi.edit(form, token.value, (r) => {
    if (r.success) {
      planeDialog.value.visible = false;
      toast.success('已提交');
      loadPlane();
    } else {
      if (r.code === -10000) {
        login(creatNext());
      }
    }
  });
};


const deletePlane = () => {
  delPlaneDialog.value.visible = true;
  planeMenu.value.visible = false;
  delPlaneDialog.value.data = planeMenu.value.data;
};

const deletePlaneConfirm = () => {
  if (onsubmit.value) {
    return;
  }
  onsubmit.value = true;
  delPlaneDialog.value.visible = false;
  ipdApi.deleteByIds({ id: delPlaneDialog.value.data.id }, token.value, (r) => {
    onsubmit.value = false;
    if (r.success) {
      toast.success('删除成功');
      planeMenu.value.data = {}
      delPlaneDialog.value.data = {};
      loadPlane();
    } else {
      if (r.code === -10000) {
        login(deletePlaneConfirm());
      }
    }
  });
};

const updateStatus = (status, finish) => {
  planeMenu.value.visible = false;
  if (finish) {
    planeMenu.value.data.position = 100;
  }
  if (status == 3) {
    if (!planeMenu.value.data.duration) {
      // 计算上一个完成的任务间隔时间
      let lastTime = new Date();
      lastTime.setHours(9)
      lastTime.setMinutes(0)
      lastTime.setSeconds(0)
      let duration = 0
      planeList.value.forEach((item, index) => {
        if (item.status == 3 && item.updateTime) {
          let d = new Date(item.updateTime);
          if (d > lastTime) {
            lastTime = d;
          }
        }
        if (item.id != planeMenu.value.data.id) {
          duration += item.duration;
        }
      })
      const getSecondsDiff = (d1, d2) =>
        Math.floor(Math.abs(d1 - d2) / 1000);

      let p = Math.min(7.5 - duration, getSecondsDiff(lastTime, new Date()) / 60 / 60);
      planeMenu.value.data.duration = Math.floor(p * 10) / 10;
    }
  }
  if (status == 4) {
    planeMenu.value.data.position = 0;
    planeMenu.value.data.duration = 0;
  }
  planeMenu.value.data.status = status;
  ipdApi.updatePosition(planeMenu.value.data, token.value, (r) => {
    if (r.success) {
      planeDialog.value.visible = false;
      toast.success('已提交');
      loadPlane();
    } else {
      if (r.code === -10000) {
        login(updateStatus(status));
      }
    }
  });
};

const sendEmail = () => {
  copyText(dailyReportDialog.value.content);
  storage.set('plane-daily-report', dailyReportDialog.value.content);
  window.open(`https://qiye.aliyun.com/alimail/entries/v5.1/compose`);
}

const copyText = (text) => {
  navigator.clipboard.writeText(text)
    .then(() => {
      toast.success('已拷贝!')
    })
    .catch(err => {
      toast.error('拷贝失败!')
    });
}

const login = (back) => {
  if (!settingDialog.value.account || !settingDialog.value.passd) {
    settingDialog.value.errorMessage = '账号和密码不能为空';
    return;
  }
  onLoading.value = true;
  ipdApi.key(settingDialog.value.account, (r) => {
    if (r.success) {
      const jsEncrypt = new JSEncrypt()
      jsEncrypt.setPublicKey(r.data)
      ipdApi.login(
        settingDialog.value.account,
        jsEncrypt.encrypt(settingDialog.value.account + settingDialog.value.passd),
        (r) => {
          if (r.success) {
            settingDialog.value.visible = false;
            storage.set('plane-setting', JSON.stringify({
              account: settingDialog.value.account,
              passd: settingDialog.value.passd,
            }));
            settingDialog.value.errorMessage = '';
            settingDialog.value.visible = false;
            onLoading.value = false;
            token.value = r.data;
            storage.set('plane-token', r.data);
            if (back) {
              back();
            }
          } else {
            settingDialog.value.errorMessage = r.message;
            onLoading.value = false;
          }
        });
    } else {
      settingDialog.value.errorMessage = `获取密钥失败${r.message}`;
      onLoading.value = false;
      return;
    }
  });
};

const getCurrentWeek = (date) => {
  const day = date.getDay(); // 0（周日）-6（周六）
  // 计算到最近周一的天数差（周一为1，周日为0）
  const diffToMonday = day === 0 ? -6 : 1 - day;
  const monday = new Date(date);
  monday.setDate(date.getDate() + diffToMonday);

  // 最后一天为周一+6天
  const sunday = new Date(monday);
  sunday.setDate(monday.getDate() + 6);
  dailyReportDate.value.start = monday;
  dailyReportDate.value.end = sunday;
}
// 日期格式化函数（补零）
const formatDate = (date) => {
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, '0');
  const day = String(date.getDate()).padStart(2, '0');
  return `${year}-${month}-${day}`;
};


const loadMonthPlane = (date) => {
  if (!token.value) {
    return;
  }
  let startDate = new Date(date);
  startDate.setDate(1); // 设置为当月的第一天
  let endDate = new Date(date);
  endDate.setMonth(endDate.getMonth() + 1); // 下个月
  endDate.setDate(1); // 设置为当月的第一天
  monthAttrs.value = []
  ipdApi.workPage(formatDate(startDate) + ' 00:00:00', formatDate(endDate) + ' 00:00:00', token.value, (r) => {
    if (r.success) {
      let planeMap = {}
      r.data.content.forEach((item) => {
        if (!planeMap[item.currentDate]) {
          planeMap[item.currentDate] = 0;
        }
        planeMap[item.currentDate] += item.duration;
      });
      for (let key in planeMap) {
        let item = planeMap[key];
        if (item < 7.5) {
          monthAttrs.value.push({
            key: `custom-mark-${key}`,
            dates: key,
            dot: {
              color: 'red',
            },
            popover: {
              label: `工时${item.toFixed(1)}H，不足7.5H`,
            },
          });
        } else if (item > 7.5) {
          monthAttrs.value.push({
            key: `custom-mark-${key}`,
            dates: key,
            dot: {
              color: 'orange',
            },
            popover: {
              label: `工时${item.toFixed(1)}H，加班${(item - 7.5).toFixed(1)}H`,
            },
          });
        } else {
          monthAttrs.value.push({
            key: `custom-mark-${key}`,
            dates: key,
            dot: {
              color: 'green',
            },
          });
        }
      }
    } else {
      if (r.code === -10000) {
        login(loadMonthPlane());
      }
    }
  });
}
const changePlaneDate = (e) => {
  planeDialog.value.data.currentDate = e.id;
  showSelectDate.value = false;
  ipdApi.workPage(planeDialog.value.data.currentDate, planeDialog.value.data.currentDate, token.value, (r) => {
    if (r.success) {
      const now = new Date();
      const target = new Date(now);
      target.setHours(19, 0, 0, 0);
      const diffMs = now - target;
      const diffHours = diffMs / (1000 * 60 * 60);

      maxTime.value = 7.5 + (diffHours > 0 ? diffHours : 0);
      r.data.content.forEach((v) => {
        if (planeDialog.value.data && v.id === planeDialog.value.data.id) {
          return
        }
        maxTime.value = maxTime.value - v.duration;
      })
      maxTime.value = parseFloat(maxTime.value.toFixed(1));
      if (planeDialog.value.data.duration > maxTime.value) {
        planeDialog.value.data.duration = maxTime.value;
      }
    } else {
      if (r.code === -10000) {
        login(loadPlane());
      }
    }
  });
}


const changePickerDate = (date) => {
  currentDate.value = date;
  console.log(currentDate.value);
  loadPlane();
}

const loadPlane = (callback) => {
  if (!token.value) {
    return;
  }
  attrs.value = []
  planeList.value = [];
  onPlaneLoading.value = true;
  ipdApi.workPage(formatDate(dailyReportDate.value.start), formatDate(dailyReportDate.value.end), token.value, (r) => {
    if (r.success) {
      let currentDateFormat = formatDate(currentDate.value);
      let planeMap = {}
      r.data.content.forEach((item) => {
        if (!planeMap[item.currentDate]) {
          planeMap[item.currentDate] = 0;
        }
        planeMap[item.currentDate] += item.duration;
        if (item.currentDate == currentDateFormat) {
          planeList.value.push(item);
        }
      });
      for (let key in planeMap) {
        let item = planeMap[key];
        if (item < 7.5) {
          attrs.value.push({
            key: `custom-mark-${key}`,
            dates: key,
            dot: {
              color: 'red',
            },
            popover: {
              label: `工时${item.toFixed(1)}H，不足7.5H`,
            },
          });
        } else if (item > 7.5) {
          attrs.value.push({
            key: `custom-mark-${key}`,
            dates: key,
            dot: {
              color: 'orange',
            },
            popover: {
              label: `工时${item.toFixed(1)}H，加班${(item - 7.5).toFixed(2)}H`,
            },
          });
        } else {
          attrs.value.push({
            key: `custom-mark-${key}`,
            dates: key,
            dot: {
              color: 'green',
            },
          });
        }
      }
      onPlaneLoading.value = false;

      if (callback) {
        callback();
      }
    } else {
      console.error('获取周报数据失败:', r);
      if (r.code === -10000) {
        login(loadPlane());
      }
    }
  });
}

const submitPlane = () => {
  if (onsubmit.value) {
    return;
  }
  onsubmit.value = true;
  if (checkSubmitPlane()) {
    if (planeDialog.value.data.id) {
      ipdApi.updatePosition(planeDialog.value.data, token.value, (r) => {
        if (r.success) {
          // 保存选项下次重用
          storage.set(`plane-data`, JSON.stringify(planeDialog.value.data));
          onsubmit.value = false;
          planeDialog.value.visible = false;
          toast.success('已提交');
          loadPlane();
        } else {
          if (r.code === -10000) {
            login(submitPlane());
          } else {
            toast.error(r.message);
          }
        }
      });
    } else {
      ipdApi.edit(planeDialog.value.data, token.value, (r) => {
        if (r.success) {
          // 保存选项下次重用
          storage.set(`plane-data`, JSON.stringify(planeDialog.value.data));
          onsubmit.value = false;
          planeDialog.value.visible = false;
          toast.success('已提交');
          loadPlane();
        } else {
          if (r.code === -10000) {
            login(submitPlane());
          } else {
            toast.error(r.message);
          }
        }
      });
    }
  } else {
    onsubmit.value = false;
  }
}

const checkSubmitPlane = () => {
  if (planeDialog.value.data.type == 4) {
    // 对外支持不需要指定项目
    planeDialog.value.data.projectId = ''
    planeDialog.value.data.projectName = ''
    planeDialog.value.data.workTaskId = ''
    planeDialog.value.data.workTaskName = ''
  }

  formErr.value = '';
  if (!planeDialog.value.data.currentDate) {
    formErr.value = '请选择任务日期';
  } else if (!planeDialog.value.data.type) {
    formErr.value = '请选择任务类型';
  } else if (planeDialog.value.data.type != 4 && !planeDialog.value.data.projectName) {
    formErr.value = '请选择所属项目';
  } else if (planeDialog.value.data.type != 4 && !planeDialog.value.data.workTaskName) {
    formErr.value = '请选择工作任务';
  } else if (planeDialog.value.data.type == 4 && !planeDialog.value.data.zentaoUrl) {
    formErr.value = '请填写禅道地址';
  } else if (!planeDialog.value.data.name) {
    formErr.value = '请输入具体工作内容';
  }

  for (let i in planeList.value) {
    if (
      planeList.value[i].currentDate == planeDialog.value.data.currentDate
      && planeList.value[i].name == planeDialog.value.data.name
      && planeList.value[i].id != planeDialog.value.data.id
      && planeList.value[i].workTaskId == planeDialog.value.data.workTaskId
    ) {
      formErr.value = '存在重复的工作内容';
      return;
    }
  }
  return formErr.value === ''
}

const loadWorkTask = () => {
  storage.get(`plane-projects-task-history-${planeDialog.value.data.projectId}`).then((r) => {
    if (r) {
      try {
        workTaskListHistory.value = JSON.parse(r);
      } catch (e) {
        console.error('解析项目历史失败:', e);
      }
    }
  })
  queryProjectsTaskForm.value.onLoading = true;
  workTaskList.value = [];
  myWorkTaskIds.value = [];
  myWorkTaskList.value = [];
  ipdApi.workTaskPage({
    ...queryProjectsTaskForm.value,
    projectId: planeDialog.value.data.projectId,
  }, token.value, (r) => {
    if (r.success) {
      const now = new Date().getTime();
      r.data.content.forEach(item => {
        if (item.endDate && item.position < 100 && new Date(item.endDate).getTime() < now) {
          item.error = true;
        }
      });
      workTaskList.value = r.data.content;
      queryProjectsTaskForm.value.onLoading = false;
    } else {
      if (r.code === -10000) {
        login(loadWorkTask());
      }
    }
  });

  if (!queryProjectsTaskForm.value.searchKey) {
    ipdApi.myWorkTaskPage({
      taskType: 1,
      pageIndex: 1,
      pageSize: 1000,
      projectId: planeDialog.value.data.projectId,
    }, token.value, (r) => {
      if (r.success) {
        const now = new Date().getTime();
        r.data.content.forEach(item => {
          item.sortStartTime = new Date(item.startDate).getTime();
          item.sortEndTime = new Date(item.endDate).getTime();
          if (item.position < 100 && item.sortEndTime < now) {
            item.error = true;
          }
          if (item.taskType == 2) {
            item.sortStartTime = item.sortStartTime * 2;
            item.sortEndTime = item.sortEndTime * 2;
          }
        });
        myWorkTaskIds.value = [];
        myWorkTaskList.value = sortByTimeRange(r.data.content);
        myWorkTaskList.value.forEach((item) => {
          myWorkTaskIds.value.push(item.id);
        });
      }
    });
  }
}

const changePosition = (value) => {
  planeDialog.value.data.position = value;
  if (value == 100) {
    planeDialog.value.data.status = 3;
  } else {
    planeDialog.value.data.status = 2;
  }
}

onMounted(async () => {
  // 检查当前日期是否为中国工作日
  checkChinaHoliday(currentDate.value instanceof Date ? currentDate.value : new Date(currentDate.value));
  // 监听日期变化，自动判断节假日
  watch(currentDate, (val) => {
    checkChinaHoliday(val instanceof Date ? val : new Date(val));
  });
  getCurrentWeek(new Date());
  token.value = await storage.get('plane-token');
  const savedSetting = await storage.get('plane-setting');
  if (savedSetting) {
    try {
      let setting = JSON.parse(savedSetting);
      settingDialog.value.account = setting.account;
      settingDialog.value.passd = setting.passd;
    } catch (e) {
      console.error('解析设置失败:', e);
    }
  }

  ipdApi.typeEnums((r) => {
    typeEnums.value = r.data;
  })
  ipdApi.statusEnums((r) => {
    statusEnums.value = r.data;
  })
  login(() => {
    loadPlane(() => {
      storage.get('addTask').then(res => {
        if (res) {
          try {
            res = JSON.parse(res);
          } catch (e) {
            console.error("parse zentao task error:", e)
          }
          if (res.title.indexOf('【') == 0) {
            let end = res.title.indexOf('】')
            res.title = '处理' + res.title.substring(end + 1) + (res.url.indexOf('bug-view-') > 0 ? "问题" : '')
          }
          showPlane({
            zentaoUrl: res.url,
            name: res.title,
            id: null,
            currentDate: formatDate(new Date()),
            duration: 0.0,
            position: 0,
            status: 2,
          })
        }
        storage.remove('addTask');
      })
    });
    loadMyProjects();
    loadRds();
  });
  // 添加全局点击事件监听器
  document.addEventListener('click', closeMenu);
  const container = planeListContainer.value;
  if (container) {
    container.addEventListener('scroll', handlePlaneListScroll);
  }
  storage.get('startup-time').then((ts) => {
    const now = new Date();
    const today = now.getFullYear() + '-' + (now.getMonth() + 1) + '-' + now.getDate();
    let lastDate = '';
    if (ts) {
      const last = new Date(Number(ts) * 1000);
      lastDate = last.getFullYear() + '-' + (last.getMonth() + 1) + '-' + last.getDate();

      if (today !== lastDate) {
        workTime.value = 0;
        return
      }
      const now = new Date();
      const y = now.getFullYear();
      const m = now.getMonth();
      const d = now.getDate();
      const nineThirty = new Date(y, m, d, 9, 0, 0, 0);

      var startupTime = checkChinaHoliday(now) && last < nineThirty ? nineThirty : last;
      // 计算 startupTime 和当前时间相差的小时数
      const diffMs = now - new Date(startupTime);
      workTime.value = (diffMs / (1000 * 60 * 60)).toFixed(1);
    }
  });
})

watch(() => dailyReportDate.value, (newVal) => {
  if (!dailyReportDialog.value.visible) {
    return;
  }
  loadDailyReport();
}, {
  deep: true
})

watch(() => planeDialog.value.data, (newVal) => {
  if (!formErr.value) {
    return;
  }
  checkSubmitPlane();
}, {
  deep: true
})


// 在组件销毁时移除事件监听器
onUnmounted(() => {
  document.removeEventListener('click', closeMenu);
  const container = planeListContainer.value;
  if (container) {
    container.removeEventListener('scroll', handlePlaneListScroll);
  }
});

</script>

<style scoped lang="less">
@import './plane.less';
</style>
<style scoped>
.spinner {
  animation: spin 0.7s linear infinite;
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }

  100% {
    transform: rotate(360deg);
  }
}
</style>